home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.000 / crossfir / crossfire-0.92.4.client / commands.c < prev    next >
C/C++ Source or Header  |  1996-04-21  |  10KB  |  359 lines

  1. /* Handles commands received by the server.  This does not necessarily
  2.  * handle all commands - some might be in other files (like init.c)
  3.  *
  4.   * this file contains most of the commands for the dispatch loop most of
  5.   * the functions are self-explanatory, the pixmap/bitmap commands recieve
  6.   * the picture, and display it.  The drawinfo command draws a string
  7.   * in the info window, the stats command updates the local copy of the stats
  8.   * and displays it. handle_query prompts the user for input.
  9.   * send_reply sends off the reply for the input.
  10.   * player command gets the player information.
  11.   * ItemCmd grabs and display information for items in the inventory
  12.   * MapScroll scrolls the map on the client by some amount
  13.   * MapCmd displays the map either with layer packing or stack packing. 
  14.   *   packing/unpacking is best understood by looking at the server code
  15.   *   (server/ericserver.c)
  16.   *   stack packing is easy, for every map entry that changed, we pack
  17.   *   1 byte for the x/y location, 1 byte for the count, and 2 bytes per
  18.   *   face in the stack.
  19.   *   layer packing is harder, but I seem to remember more efficient:
  20.   *   first we pack in a list of all map cells that changed and are now
  21.   *   empty.  The end of this list is a 255, which is bigger that 121, the
  22.   *   maximum packed map location.  
  23.   *   For each changed location we also pack in a list of all the faces and
  24.   *   X/Y coordinates by layer, where the layer is the depth in the map.
  25.   *   This essentially takes slices through the map rather than stacks.
  26.   *   Then for each layer, (max is MAXMAPCELLFACES, a bad name) we start
  27.   *   packing the layer into the message.  First we pack in a face, then
  28.   *   for each place on the layer with the same face, we pack in the x/y
  29.   *   location.  We mark the last x/y location with the high bit on 
  30.   *   (11*11 = 121 < 128).  We then continue on with the next face, which
  31.   *   is why the code marks the faces as -1 if they are finished.  Finally
  32.   *   we mark the last face in the layer again with the high bit, clearly
  33.   *   limiting the total number of faces to 32767, the code comments it's
  34.   *   16384, I'm not clear why, but the second bit may be used somewhere
  35.   *   else as well.
  36.   *   The unpacking routines basically perform the opposite operations.
  37.   */
  38.  
  39. #include <client.h>
  40. #include <X11/Xlib.h>
  41. /* these are just dummy functions for right now */
  42.  
  43. void look_at(int x, int y) {}
  44.  
  45. void PrintMsg(ArgList msg)
  46. {
  47.   printf("Command: %s\n",ArgList_getString(msg,1));
  48. }
  49.  
  50. void PixMapCmd(ArgList msg)
  51. {
  52.   char *buf;
  53.   unsigned long buflen;
  54. /*  printf("Recieveing Pixmap #%ld\n",ArgList_getLong(msg,2));*/
  55.  
  56.   buf = ArgList_getBuf(msg,3,&buflen);
  57. /*  printf("%s\n",buf);*/
  58.   display_newpixmap(ArgList_getLong(msg,2),buf,buflen);
  59. }
  60.  
  61. void BitMapCmd(ArgList msg)
  62. {
  63.   char *buf;
  64.   unsigned long buflen;
  65.   long num = ArgList_getLong(msg,2);
  66.   long fg = ArgList_getChar(msg,3);
  67.   long bg = ArgList_getChar(msg,4);
  68.  
  69. /*  printf("Recieveing Pixmap #%ld\n",ArgList_getLong(msg,2));*/
  70.  
  71.   buf = ArgList_getBuf(msg,5,&buflen);
  72.   if (buflen != 24*3) {
  73.     fprintf(stderr,"Incorrect length on bitmap buffer should be %d was %ld\n",
  74.           24*3,buflen);
  75.     abort();
  76.   }
  77. /*  printf("%s\n",buf);*/
  78.   display_newbitmap(num,fg,bg,buf);
  79. }
  80.  
  81.  
  82. void DrawInfoCmd(ArgList msg)
  83. {
  84.   int color=ArgList_getChar(msg,2);
  85.  
  86. /*  printf("Draw_info: %s\n",ArgList_getString(msg,3));*/
  87.   if (color!=NDI_BLACK)
  88.       draw_color_info(color, ArgList_getString(msg,3));
  89.   else
  90.       draw_info(ArgList_getString(msg,3),NDI_BLACK);
  91.  
  92. }
  93.  
  94. void StatsCmd(ArgList msg)
  95. {
  96.   int i,m;
  97.   int c;
  98.  
  99.   m = ArgList_getLength(msg);
  100.   for(i=2;i<m;i+=2) {
  101.     c = ArgList_getChar(msg,i);
  102.     switch (c) {
  103.      case CS_STAT_HP:    cpl.stats.hp=ArgList_getLong(msg,i+1);break;
  104.      case CS_STAT_MAXHP:cpl.stats.maxhp=ArgList_getLong(msg,i+1);break;
  105.      case CS_STAT_SP:    cpl.stats.sp=ArgList_getLong(msg,i+1);break;
  106.      case CS_STAT_MAXSP:cpl.stats.maxsp=ArgList_getLong(msg,i+1);break;
  107.      case CS_STAT_STR:    cpl.stats.Str=ArgList_getLong(msg,i+1);break;
  108.      case CS_STAT_INT:    cpl.stats.Int=ArgList_getLong(msg,i+1);break;
  109.      case CS_STAT_WIS:    cpl.stats.Wis=ArgList_getLong(msg,i+1);break;
  110.      case CS_STAT_DEX:    cpl.stats.Dex=ArgList_getLong(msg,i+1);break;
  111.      case CS_STAT_CON:    cpl.stats.Con=ArgList_getLong(msg,i+1);break;
  112.      case CS_STAT_CHA:  cpl.stats.Cha=ArgList_getLong(msg,i+1);break;
  113.      case CS_STAT_EXP:  cpl.stats.exp=ArgList_getLong(msg,i+1);break;
  114.      case CS_STAT_LEVEL:cpl.stats.level=ArgList_getLong(msg,i+1);break;
  115.      case CS_STAT_WC:   cpl.stats.wc=ArgList_getLong(msg,i+1);break;
  116.      case CS_STAT_AC:   cpl.stats.ac=ArgList_getLong(msg,i+1);break;
  117.      case CS_STAT_DAM:  cpl.stats.dam=ArgList_getLong(msg,i+1);break;
  118.      case CS_STAT_ARMOUR:cpl.stats.armor=ArgList_getLong(msg,i+1);break;
  119.      case CS_STAT_SPEED: cpl.stats.speed=ArgList_getLong(msg,i+1);break;
  120.      case CS_STAT_FOOD:  cpl.stats.food=ArgList_getLong(msg,i+1);break;
  121.      case CS_STAT_WEAP_SP:cpl.stats.weapon_sp=ArgList_getLong(msg,i+1);break;
  122.      case CS_STAT_POW:    cpl.stats.Pow=ArgList_getLong(msg,i+1);break;
  123.      case CS_STAT_GRACE:cpl.stats.grace=ArgList_getLong(msg,i+1);break;
  124.      case CS_STAT_MAXGRACE:cpl.stats.maxgrace=ArgList_getLong(msg,i+1);break;
  125.  
  126.      case CS_STAT_RANGE: {
  127.     strcpy(cpl.range,ArgList_getString(msg, i+1));
  128.     break;
  129.      }
  130.      case CS_STAT_TITLE: {
  131.     strcpy(cpl.title,ArgList_getString(msg, i+1));
  132.     break;
  133.      }
  134.  
  135.      default:
  136.       printf("Unknown stat number %d\n",c);
  137.     }
  138.   }
  139.   draw_stats(0);
  140.   draw_message_window(0);
  141. }
  142.  
  143. void handle_query (ArgList msg)
  144. {
  145.     char *buf2;
  146.     uint8 flags = ArgList_getChar(msg, 2);
  147.  
  148.     buf2 = ArgList_getString(msg,3);
  149.  
  150.     /* If we just get passed an empty string, why draw this? */
  151.     if (*buf2) draw_prompt(buf2);
  152.  
  153.     /* Yes/no - don't do anything with it now */
  154.     if (flags & CS_QUERY_YESNO) {}
  155.  
  156.     /* one character response expected */
  157.     if (flags & CS_QUERY_SINGLECHAR)
  158.         cpl.input_state = Reply_One;
  159.     else
  160.         cpl.input_state = Reply_Many;
  161.  
  162.     if (flags & CS_QUERY_HIDEINPUT)        /* no echo */
  163.         cpl.no_echo=1;
  164.  
  165.       fprintf(stderr,"Received query.  Input state now %d\n", cpl.input_state);
  166. }
  167.  
  168. /* Sends a reply to the server.  text contains the null terminated
  169.  * string of text to send.  This function basically just packs
  170.  * the stuff up.
  171.  */
  172.  
  173. void send_reply(char *text)
  174. {
  175.     ArgList msg;
  176.  
  177.     msg = ArgList_create();
  178.     ArgList_addLong(msg, STRINGCOMMAND);
  179.     ArgList_addString(msg,"reply");
  180.     ArgList_addString(msg,text);
  181.     ArgList_send(conns[0], msg);
  182.     ArgList_destroy(msg);
  183. }
  184.  
  185.  
  186. #define GET_LONG(p,l) ((l)  = (unsigned long)(*(p)++ & 0xFF) << 24,\
  187.         (l) += (unsigned long)(*(p)++ & 0xFF) << 16,\
  188.         (l) += (unsigned long)(*(p)++ & 0xFF) << 8,\
  189.         (l) += (unsigned long)(*(p)++ & 0xFF))
  190. #define GET_STRING(p,s) (strcpy(s,p), p+=strlen(p)+1)
  191.  
  192.  
  193. /* This function copies relevant data from the archetype to the
  194.  * object.  Only copies data that was not set in the object
  195.  * structure.
  196.  *
  197.  */
  198.  
  199. void PlayerCmd(ArgList msg)
  200. {
  201.     char name[MAX_BUF], *ptr;
  202.     long tag, weight, face;
  203.  
  204.     ptr = ArgList_getBuf (msg, 2, NULL);
  205.     /* The only really needed thing is a tag, but sending some other 
  206.      * information can be sended in same time
  207.      */
  208.     GET_LONG(ptr, tag);
  209.     GET_LONG(ptr, weight);
  210.     GET_LONG(ptr, face);
  211.     GET_STRING(ptr, name);
  212.     new_player(tag, name, weight, face);
  213. }
  214.  
  215. void item_actions (item *op)
  216. {
  217.     if (op->open) {
  218.     open_container (op);
  219.     } else if (op->was_open) {
  220.     close_container (op);
  221.     }
  222. /*
  223.     if (op->env == cpl.below) {
  224.     check_auto_pickup (op);
  225.     }
  226. */
  227. }
  228.  
  229. void ItemCmd(ArgList msg)
  230. {
  231.     long weight, loc, tag, face, flags, len;
  232.     char name[MAX_BUF], *endptr, *ptr;
  233.  
  234.     ptr = ArgList_getBuf (msg, 2, &len);
  235.     endptr = ptr + len;
  236.     GET_LONG(ptr, loc);
  237.  
  238.     if (ptr == endptr)
  239.     /* An empty item command can be used to delete the whole
  240.      * inventory of item 'loc'. Esspecially if loc is 0, then
  241.      * there is no floor under the player.
  242.      */
  243.     delete_item_inventory(loc);
  244.     else if (loc < 0) { /* delele following items */
  245.     while (ptr < endptr) {
  246.         GET_LONG(ptr, tag);
  247.         delete_item(tag);
  248.     }
  249.     } else {
  250.     while (ptr < endptr) {
  251.         GET_LONG(ptr, tag);
  252.         GET_LONG(ptr, flags);
  253.         GET_LONG(ptr, weight);
  254.         GET_LONG(ptr, face);
  255.         GET_STRING(ptr, name);
  256.         if (flags & 0x0100) /* tmp. solution, clear the inventory */
  257.         delete_item_inventory(loc);     /* deletes all items */
  258.         update_item (tag, loc, name, weight, face, flags);
  259.         item_actions (locate_item(tag));
  260.     }
  261.     }
  262. /*    draw_lists ();*/ 
  263. }
  264.  
  265.  
  266. void Map_unpackstack(unsigned char *cur,unsigned char *end)
  267. {
  268.   long x,y,face,nfaces;
  269.  
  270.   while(cur < end) {
  271.     x = (*cur >> 4) & 0x0F;
  272.     y = (*cur) & 0x0F;
  273.     cur++;
  274.     nfaces = *cur;
  275.     cur++;
  276.     display_map_clearcell(x,y);
  277.     while(nfaces>0) {
  278.       face = *cur << 8;
  279.       cur++;
  280.       face |= *cur;
  281.       cur++;
  282.       display_map_addbelow(x,y,face);
  283.       nfaces--;
  284.     }
  285.   }
  286. }
  287.  
  288. void Map_unpacklayer(unsigned char *cur,unsigned char *end)
  289. {
  290.   long x,y,face;
  291.   int xy;
  292.   int clear = 1;
  293.   unsigned char *fcur;
  294.   
  295.   while (cur < end && *cur != 255) {
  296.     xy = *cur;
  297.     cur++;
  298.     x = xy / 11;
  299.     y = xy % 11;
  300.     display_map_clearcell(x,y);
  301.   }
  302.   cur++;
  303.   while(cur < end) {
  304.     fcur = cur;
  305.     face = *cur & 0x7f;
  306.     cur++;
  307.     face = (face << 8) | *cur;
  308.     cur++;
  309.     while(1) {
  310.       xy = *cur & 0x7f;
  311.       x = xy / 11;
  312.       y = xy % 11;
  313.       if (clear) {
  314.     display_map_clearcell(x,y);
  315.       }
  316.       display_map_addbelow(x,y,face);
  317.       xy = *cur;
  318.       cur++;
  319.       if (xy & 128) {
  320.     break;
  321.       }
  322.       if (cur==end) {
  323.     fprintf(stderr,"Incorrectly packed map.\n");
  324.     abort();
  325.       }
  326.     }
  327.     if (*fcur & 128) 
  328.       clear = 0; /* end of first layer (or some layer after the first) */
  329.   }
  330. }
  331.  
  332. void MapCmd(ArgList msg)
  333. {
  334.   unsigned char *buf,*end;
  335.   unsigned long buflen;
  336.   
  337. /*  printf("Recieving map\n");*/
  338.   buf = ArgList_getBuf(msg,2,&buflen);
  339.   end = buf + buflen;
  340.  
  341.   display_map_startupdate();
  342. #if 1
  343.   Map_unpacklayer(buf,end);
  344. #else
  345.   Map_unpackstack(buf,end);
  346. #endif
  347.  
  348.   display_map_doneupdate();
  349. }
  350.  
  351. void map_scrollCmd(ArgList msg)
  352. {
  353.   int dx,dy;
  354.  
  355.   dx = ArgList_getLong(msg,2);
  356.   dy = ArgList_getLong(msg,3);
  357.   display_mapscroll(dx,dy);
  358. }
  359.